package com.rss.inbound.processor;

import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.rss.inbound.beans.RssEntry;
import com.rss.inbound.beans.RssSrc;
import com.rss.inbound.beans.Sts;
import com.rss.inbound.dao.RssEntryDAO;
import com.rss.inbound.dao.RssSrcDAO;
import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

public class RSSDownloader {
	final static Log log = LogFactory.getLog(RSSDownloader.class);
	private static ClassPathXmlApplicationContext applicationContext;
	
	private static RssSrcDAO rssSrcDAO = null;
	
	private static RssEntryDAO rssEntryDAO = null;
		
	/**
	 * @param args
	 */
	public static void main(String[] args) {
    	try {
    		
    		URL feedSource = new URL("http://feeds.gawker.com/Gizmodo/full");
    		SyndFeedInput input = new SyndFeedInput();
    		SyndFeed feed = input.build(new XmlReader(feedSource));
    		
    		log.info("==================");
    		log.info(feed.toString());
    		log.info("==================");
    		
	    	/*log.info("Initializing Spring context.");
			applicationContext = new ClassPathXmlApplicationContext("com/rss/inbound/config/spring-config.xml");
		    log.info("Spring context initialized.");
		    
		    rssSrcDAO = (RssSrcDAO) applicationContext.getBean("rssSrcDAOImpl");
		    rssEntryDAO = (RssEntryDAO) applicationContext.getBean("rssEntryDAOImpl");
		    
		    List<RssSrc> rssSrcList = rssSrcDAO.getAllRssSrcs();
	
			List<RssEntry> rssEntries = new ArrayList<RssEntry>();
			
			for(RssSrc rssSrc : rssSrcList)
		    {
	    		URL feedSource = new URL(rssSrc.getRssSrcDwnldLnk());
	    		SyndFeedInput input = new SyndFeedInput();
	    		SyndFeed feed = input.build(new XmlReader(feedSource));
	    		
	    		log.info("==================");
	    		log.info(feed.toString());
	    		log.info("==================");
	    		
	    		int entryNumber = 1;
	    		
	    		if(rssSrc.getRssSrcTtl().equalsIgnoreCase("Engadget"))
	    		{
	    			log.info("Processing RSS Source ==> " + rssSrc.getRssSrcTtl());
	    			
					List<SyndEntry> engadgetEntries = feed.getEntries();
					
					log.info("No. of active entries today for Engadget - " + engadgetEntries.size());
					
					Sts activeRssEntrySts = new Sts();
					activeRssEntrySts.setIdSts(3);
					
					for (SyndEntry engadgetEntry : engadgetEntries)
					{
						log.info("Processing RSS Entry # " + (entryNumber++) + " ==> " + engadgetEntry.getTitle());
						//log.info("Processing RSS Description ==> " + engadgetEntry.getDescription().getValue());
						
						boolean isDuplicate = checkForDupeEntry(engadgetEntry,rssSrc.getRssSrcTtl());
						
						if(!isDuplicate)
						{
							RssEntry rssEntry = new RssEntry();
							rssEntry.setRssSrc(rssSrc);
							rssEntry.setAthr(engadgetEntry.getAuthor());
							rssEntry.setTtl(engadgetEntry.getTitle());
							rssEntry.setEntryLnk(engadgetEntry.getUri());
							rssEntry.setCntn(engadgetEntry.getDescription().getValue().getBytes());
							rssEntry.setCntnFrmt(engadgetEntry.getDescription().getType());
							rssEntry.setPubDttm(engadgetEntry.getPublishedDate());
							rssEntry.setSts(activeRssEntrySts);
							rssEntry.setEntryStsDttm(new Date());
							rssEntry.setCreatBy("RssDownloaderBatch");
							rssEntry.setCreatDttm(new Date());
							rssEntry.setLastModBy("RssDownloaderBatch");
							rssEntry.setLastModDttm(new Date());
							
							rssEntries.add(rssEntry);
						}
					}
	    		}
	    		else if(rssSrc.getRssSrcTtl().startsWith("TechCrunch"))
	    		{
	    			log.info("==================");
		    		log.info(feed.toString());
		    		log.info("==================");
	    			
	    			log.info("Processing RSS Source ==> " + rssSrc.getRssSrcTtl());
	    			
					List<SyndEntry> techCrunchEntries = feed.getEntries();
					
					log.info("No. of active entries today for TechCrunch - " + techCrunchEntries.size());
					
					Sts activeRssEntrySts = new Sts();
					activeRssEntrySts.setIdSts(3);
					
					for (SyndEntry techCrunchEntry : techCrunchEntries)
					{
						log.info("Processing RSS Entry # " + (entryNumber++) + " ==> " + techCrunchEntry.getTitle());
						//log.info("Processing RSS Description ==> " + techCrunchEntry.getDescription().getValue());
						
						boolean isDuplicate = checkForDupeEntry(techCrunchEntry,rssSrc.getRssSrcTtl());
						
						if(!isDuplicate)
						{
							RssEntry rssEntry = new RssEntry();
							rssEntry.setRssSrc(rssSrc);
							rssEntry.setAthr(techCrunchEntry.getAuthor());
							rssEntry.setTtl(techCrunchEntry.getTitle());
							rssEntry.setEntryLnk(techCrunchEntry.getUri());
							rssEntry.setDesc(techCrunchEntry.getDescription().getValue().getBytes());
							
							List<SyndContent> syndContentList = techCrunchEntry.getContents();
							SyndContent syndContent =  syndContentList.get(0);
							rssEntry.setCntn(syndContent.getValue().getBytes());
							rssEntry.setCntnFrmt(syndContent.getType());

							rssEntry.setPubDttm(techCrunchEntry.getPublishedDate());
							rssEntry.setSts(activeRssEntrySts);
							rssEntry.setEntryStsDttm(new Date());
							rssEntry.setCreatBy("RssDownloaderBatch");
							rssEntry.setCreatDttm(new Date());
							rssEntry.setLastModBy("RssDownloaderBatch");
							rssEntry.setLastModDttm(new Date());
							
							rssEntries.add(rssEntry);
						}
					}
	    		}
	    		else if(rssSrc.getRssSrcTtl().equalsIgnoreCase("Ars Technica"))
	    		{
	    			log.info("Processing RSS Source ==> " + rssSrc.getRssSrcTtl());
	    			
					List<SyndEntry> arsTechnicaEntries = feed.getEntries();
					
					log.info("No. of active entries today for Ars Technica - " + arsTechnicaEntries.size());

					log.info("==================");
		    		log.info(feed.toString());
		    		log.info("==================");
	   			}
			}
			if(rssEntries.size() > 0)
			{
				log.info("Persisting RSS Entries to DB...");
				rssEntryDAO.persistList(rssEntries);
				log.info("Done saving RSS Entries to DB");
			}
			else
			{
				log.info("Nothing to update into DB bro!");
			}
	    */
    		
    	}
   	 	catch (Exception e) {
   	 		log.error(e);
		}
	}
	
	private static boolean checkForDupeEntry(SyndEntry rssEntry, String rssSourceTitle) {
		boolean isDupe = false;
		String rssEntryLink = rssEntry.getUri();
		List<RssEntry> matchingRssEntries = rssEntryDAO.findMatchingEntries(rssEntryLink);
		
		for (RssEntry matchingRssEntry : matchingRssEntries)
		{
			String existingEntryDesc = null;
			
			if (rssSourceTitle.equalsIgnoreCase("Engadget"))
			{
				// For engadget.com the entry description and content are the same in the RSS Feed!
				existingEntryDesc = new String(matchingRssEntry.getCntn());
			} 
			else if (rssSourceTitle.equalsIgnoreCase("TechCrunch"))
			{
				// For techcrunch.com the entry description and content are NOT the same in the RSS Feed!
				existingEntryDesc = new String(matchingRssEntry.getDesc());
			}
			
			if(existingEntryDesc.equalsIgnoreCase(rssEntry.getDescription().getValue()))
			{
				log.info("Found an existing entry with the same link and content...Hence marking this one to DUPE status");
				isDupe = true;
			}
			else
			{
				log.info("Updating the Entry's Content - Since there is only change in content with in the same link...");
				matchingRssEntry.setCntn(rssEntry.getDescription().getValue().getBytes());
				matchingRssEntry.setLastModBy("RssDownloaderBatch");
				matchingRssEntry.setLastModDttm(new Date());
				matchingRssEntry.setPubDttm(rssEntry.getPublishedDate());
				rssEntryDAO.updateContent(matchingRssEntry);
				log.info("Done updating the Entry's Content...");
				
				//Setting dupe flag to true to make sure another entry is not added to the database
				log.info("Setting entry to DUPE status...for not adding another entry to the DB");
				isDupe=true;
			}
		}
		return isDupe;
	}
}
